package com.piece.file.client.local;

import com.piece.core.framework.exception.ErrorCode;
import com.piece.core.framework.exception.FrameWorkException;
import com.piece.core.framework.util.file.FileUtil;
import com.piece.core.framework.util.object.BeanUtil;
import com.piece.core.framework.util.security.coder.MD5Coder;
import com.piece.file.client.AbstractFileClient;
import com.piece.file.model.TbSysFile;
import lombok.extern.slf4j.Slf4j;
import java.io.*;
import java.util.List;

/**
 * 本地文件客户端
 */
@Slf4j
public class LocalFileClient extends AbstractFileClient<LocalFileClientConfig> {

    public LocalFileClient(String name, LocalFileClientConfig config) {
        super(name, config);
    }

    @Override
    protected void doInit() {
        if (!config.getBasePath().endsWith(File.separator)) {
            config.setBasePath(config.getBasePath() + File.separator);
        }
    }

    @Override
    public TbSysFile writeToServerStore(byte[] bytes, String path, String name, String md5, boolean stat) throws Exception {
        TbSysFile file = new TbSysFile();
        file.setMd5(md5);
        try {
            String storePathAndName = path + File.separator + name;
            String dest = stat ? storePathAndName : config.getBasePath() + storePathAndName;

            List<TbSysFile> existFiles = tbSysFileService.findFileByMd5(md5);
            if (null != existFiles && existFiles.size() > 0) {
                file.setServerFileName(existFiles.get(0).getServerFileName());
                file.setServerPath(existFiles.get(0).getServerPath());
                file.setLocalPath(existFiles.get(0).getLocalPath());
                return file;
            }

            FileUtil.writeByteArrayToFile(new File(dest), bytes);
            file.setServerFileName(name);
            file.setServerPath(path);
            file.setLocalPath(dest);
            return file;
        } catch (IOException e) {
            log.error("上传本地文件异常：{}", e.getMessage());
            throw new FrameWorkException(ErrorCode.UPLOAD);
        }
    }

    @Override
    public InputStream downloadFile(TbSysFile tbSysFile) throws Exception {
        File file = new File(tbSysFile.getLocalPath());
        try {
            if (!file.exists()) {
                throw new FrameWorkException(ErrorCode.NOT_FOUND);
            }

            return new FileInputStream(file);
        } catch (FileNotFoundException e) {
            log.error("上传本地文件异常：{}", e.getMessage());
            throw new FrameWorkException(ErrorCode.DOWNLOAD);
        }
    }

    @Override
    public void updateFile(TbSysFile file) {
        String path = file.getLocalPath();
        File dir = new File(path);
        try {
            // 文件存在, 且不是目录
            if (dir.exists() && !dir.isDirectory()) {
                dir.delete();
            }

            byte[] bytes = FileUtil.toByte(file.getFileInputStream());
            String md5 = MD5Coder.md5File(bytes);

            // 重新上传文件
            TbSysFile temp = writeToServerStore(bytes, path, file.getServerFileName(), md5, false);
            BeanUtil.copyProperties(file, temp);
            updateTbSysFile(temp);
        } catch (Exception e) {
            log.error("本地文件更新异常：{}", e.getMessage());
            throw new FrameWorkException(new ErrorCode(e.getMessage()));
        }
    }

    @Override
    public void deleteFile(TbSysFile file) {
        String path = file.getLocalPath();
        File dir = new File(path);
        try {
            deleteTbSysFile(file);

            if (checkMd5(file)) {
                return;
            }
            // 文件存在, 且不是目录
            if (dir.exists() && !dir.isDirectory()) {
                dir.delete();
            }
        } catch (Exception e) {
            log.error("本地文件删除异常：{}", e.getMessage());
            throw new FrameWorkException(ErrorCode.DELETE);
        }
    }
}
